package ui.swing.tree.filesystem;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

import javax.swing.ButtonGroup;
import javax.swing.DefaultListModel;
import javax.swing.JCheckBoxMenuItem;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTable;
import javax.swing.JTree;
import javax.swing.border.BevelBorder;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreePath;
import javax.swing.tree.TreeSelectionModel;

import ui.swing.table.renderer.TabListCellRenderer;


public class MyFileExplorer extends JFrame implements TreeSelectionListener, ActionListener, ListSelectionListener {

	private static final long serialVersionUID = -9058758323234579201L;

	// 左边的树形文件夹结构，用树存放
	JTree v_treeFileSystem;

	// v_treeFileSystem的模型
	FileSystemTreeModel v_trmFileSystem;

	// 右边为“显示列表”时的文件清单
	JList v_listFiles;
	
	// 右边为“显示详细信息”时的文件表
	JTable v_tblFiles;
	
	// v_tblFiles的模型
	DefaultTableModel v_tbmFiles;

	// 存放树形文件夹结构的ScrollPane
	JScrollPane v_scr4Tree;

	// 存放文件表的ScrollPane
	JScrollPane v_scr4Files;

	// 主窗口上的分页面板
	JSplitPane v_splPane;

	// 工具栏
	JMenuBar v_mbar;

	// 菜单"文件"
	JMenu v_menuFile;

	// 菜单"编辑"
	JMenu v_menuEdit;

	// 菜单"查看"
	JMenu v_menuView;
	
	// 菜单项"在左边也显示文件"
	JMenuItem v_miShowFileInTree;
	
	// 菜单项"详细"
	JMenuItem v_miDetail;

	// 菜单项"列表"
	JMenuItem v_miList;

	// 主界面容器
	JPanel v_mainPane;

	// 状态条面板
	JPanel v_pnlStatus;

	// 状态条文字
	JLabel v_lblStatus;
	
	// 地址栏面板
	JPanel v_pnlURL;
	
	// 地址栏
	MemComboBox v_cmbURL;
	
	// 浏览器上下文，用于储存各个视图都会用到的数据（可能上下文这个名字不恰当，不够凑合了先=.=）
	FileExplorerContext v_context;

	public MyFileExplorer() {
		initUI();
		registerListener();

		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
	}

	private void initUI() {
		setTitle("Q版资源管理器：）");
		setBounds(50, 50, 880, 680);
		//SwingUtil.setLookAndFeel();

		setJMenuBar(getV_mbar());
		getContentPane().add(getV_pnlURL(), BorderLayout.NORTH);
		getContentPane().add(getV_mainPane(), BorderLayout.CENTER);
		getContentPane().add(getV_pnlStatus(), BorderLayout.SOUTH);

		setDefaultCloseOperation(EXIT_ON_CLOSE);
		setVisible(true);
	}
	
	private void loadChoosedDirToRight() {
		int curView = getV_context().getCurrentRightViewComponent();
		switch(curView) {
		case FileExplorerContext.TABLE_VIEW: 
			loadChoosedDirToTable();
			if(getV_scr4Files().getViewport().getView() != getV_tblFiles())
				getV_scr4Files().setViewportView(getV_tblFiles());
			break;
		case FileExplorerContext.LIST_VIEW:
			loadChoosedDirToList();
			if(getV_scr4Files().getViewport().getView() != getV_listFiles())
				getV_scr4Files().setViewportView(getV_listFiles());
			break;
		}
	}
	
	// 将选择的目录下的文件显示在右边
	private void loadChoosedDirToTable() {
		File dirToLoad = getV_context().getFile_choosed();
		if(dirToLoad == null) { // 虚节点为null
			return;
		}
		if(!dirToLoad.isDirectory()) { // 对于一些没放关盘的光驱，也是有用的
			return;
		}
		File[] files = dirToLoad.listFiles();
		if(files == null)
			return;
		// 清空现有记录
		for(int i = 0, t = getV_tbmFiles().getRowCount(); i < t ;i++) {
			getV_tbmFiles().removeRow(0);
		}
		
		// 向表格中添加数据
		for(File aFile : files) {
			String fileName;
			String type;
			long fileLength;
			String lastModified;
			
			fileName = aFile.getName();
			SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
			lastModified = sdf.format(new Date(aFile.lastModified()));
			if(aFile.isDirectory()) {
				type = "文件夹";
				fileLength = 0;
				getV_tbmFiles().addRow(new Object[]{fileName, type, null, lastModified});
			}
			else {
				type = fileName.substring(fileName.lastIndexOf('.') + 1); //TODO
				fileLength = aFile.length();
				String sFilelength = NumberFormat.getInstance().format(fileLength);
				getV_tbmFiles().addRow(new Object[]{fileName, type, sFilelength, lastModified});
			}
		}
		// getV_treeFileSystem().revalidate();
	}
	
	private void loadChoosedDirToList() {
		File dirToLoad = getV_context().getFile_choosed();
		if(!dirToLoad.isDirectory()) {
			return;
		}
		File[] files = dirToLoad.listFiles();
		if(files == null)
			return;
		DefaultListModel listModel =(DefaultListModel)getV_listFiles().getModel();
		listModel.clear();
		// 向列表中添加数据
		for(File aFile : files) {
			String fileName = aFile.getName();
			if(aFile.isDirectory()) {
				fileName += "(文件夹)";
			}
			listModel.addElement(fileName);
		}
	}
	
	private void registerListener() {
		TreeSelectionModel v_selectionModel = getV_treeFileSystem().getSelectionModel();
		v_selectionModel.addTreeSelectionListener(this);
		v_selectionModel.setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION);
		getV_cmbURL().addActionListener(this);
		getV_tblFiles().getSelectionModel().addListSelectionListener(this);
	}

	public static void main(String[] args) {
		new MyFileExplorer();
		System.out.println(System.getProperty("user.dir"));
	}

	public void valueChanged(TreeSelectionEvent e) {
		// TODO Auto-generated method stub
		DefaultMutableTreeNode selNode = (DefaultMutableTreeNode)getV_treeFileSystem().getLastSelectedPathComponent();
		// 有时会有未选择Node，但是触发了valueChanged的情况，比如选择了树的一个文件节点，然后关闭了这个节点所在的父节点
		if(selNode == null) {
			return;
		}
		// 将选择的节点放入上下文，后边的相关操作都从上下文中取节点
		getV_context().setNode_choosed(selNode);
		
		changePnlURLBySelNode();
		changeTreeBySelNode();
		changeRightBySelNode();
		changeStatusLabelBySelNode();
	}

	public void valueChanged(ListSelectionEvent e) {
		System.out.println(e.toString());
		int[] rowIndices = getV_tblFiles().getSelectedRows();
		if(rowIndices.length == 0)
			return;
		if(rowIndices.length == 1){
			int rowIndex = getV_tblFiles().getSelectedRow();
			if(rowIndex == -1) {
				return;
			}
			Object[] rowInfo = new Object[getV_tblFiles().getColumnCount()];
			for(int i=0; i<rowInfo.length ; i++) {
				rowInfo[i] = getV_tblFiles().getValueAt(rowIndex, i);
			}
			StringBuilder sbuilder = new StringBuilder();
			sbuilder.append("文件类型：").append(rowInfo[1].toString()).append(" ");
			if(rowInfo[2] != null) {
				sbuilder.append("大小：").append(rowInfo[2]).append("字节  ");
			}
			sbuilder.append("修改日期：").append((rowInfo[3]));
			getV_lblStatus().setText(sbuilder.toString());
		} else {
			/*List<Object[]> rowInfos = new ArrayList<Object[]>();
			for(int r : rowIndices) {
				Object[] rowInfo = new Object[getV_tblFiles().getColumnCount()];
				for(int col = 0; col < rowInfo.length ; col++) {
					rowInfo[col] = getV_tblFiles().getValueAt(r, col);
				}
				rowInfos.add(rowInfo);
			}*/
			int selectCount = rowIndices.length;
			long totalSize = 0;
			for(int r : rowIndices) {
				Object size = getV_tblFiles().getValueAt(r, 2);
				if(size == null)
					continue;
				else if(size instanceof String)
				{
					try {
						size = NumberFormat.getInstance().parse((String)size);
					} catch (ParseException e1) {
						e1.printStackTrace();
					}
					totalSize += (Long)size;
				}
			}
			StringBuilder sbuilder = new StringBuilder();
			sbuilder.append("选择了：").append(selectCount).append("个文件 ");			
			sbuilder.append("总大小：").append(NumberFormat.getInstance(Locale.US).format(totalSize)).append("字节 ");
			getV_lblStatus().setText(sbuilder.toString());
		}
	}
		
	
	// 根据上下文中的选中节点改变左边的结构
	// 主要包括1.在树中根据文件系统目录结构为选中的节点添加子节点;2.之后展开选定的节点
	private void changeTreeBySelNode() {
		DefaultMutableTreeNode selNode = getV_context().getNode_choosed();
		if(selNode == getV_trmFileSystem().getRoot()) {
			return;
		}
		else {
			getV_trmFileSystem().loadFileSystemPath(selNode);
		}
		getV_treeFileSystem().expandPath(new TreePath(selNode.getPath()));
	}
	
	private void changeRightBySelNode() {
		loadChoosedDirToRight();
	}
	
	private void changePnlURLBySelNode() {
		String location = getV_context().getFn_choosed().getLocation();
		getV_cmbURL().getEditor().setItem(location);
	}
	
	private void changeStatusLabelBySelNode() {
		 File file = getV_context().getFile_choosed();
		 if(!file.isDirectory())
			 return;
		 int subCount = file.listFiles() == null ? 0 : file.listFiles().length;
		 getV_lblStatus().setText("共有："+subCount+" 个对象");
	}

	public void actionPerformed(ActionEvent e) {
		Object source = e.getSource();
		// 在左边也显示文件
		if(source == getV_miShowFileInTree()) {
			boolean booleanValue = getV_miShowFileInTree().isSelected();
			getV_trmFileSystem().setDirectoryOnly(!booleanValue);
			getV_trmFileSystem().init();
		}
		if(source == getV_miDetail()) {
			getV_context().setCurrentRightViewComponent(FileExplorerContext.TABLE_VIEW);
			loadChoosedDirToRight();
		}
		if(source == getV_miList()) {
			getV_context().setCurrentRightViewComponent(FileExplorerContext.LIST_VIEW);
			loadChoosedDirToRight();
		}
		if(source == getV_cmbURL()) {
			String inputPath = getV_cmbURL().getSelectedItem().toString();
			File f = new File(inputPath);
			DefaultMutableTreeNode tNode = getV_trmFileSystem().findNodeByFile(f);
			if(tNode != null) {
				doExpandByFile(f, tNode);
				getV_cmbURL().add(inputPath);
			} else {
				JOptionPane.showMessageDialog(this, "指定路径无效", "信息", JOptionPane.INFORMATION_MESSAGE);
			}
		}
	}
	
	private void doExpandByFile(File file, DefaultMutableTreeNode tNode) {
		String destPathString = file.getAbsolutePath();
		String startPath = ((FileNode)tNode.getUserObject()).getLocation();
		
		String deltaPath = destPathString.substring(startPath.length(), destPathString.length());
		String[] addPaths = deltaPath.split("\\\\");

		getV_trmFileSystem().loadFileSystemPath(tNode);
		
		DefaultMutableTreeNode curNode = tNode;
		for(String c : addPaths) {
			for(int i=0; i<tNode.getChildCount(); i++) {
				DefaultMutableTreeNode childNode = (DefaultMutableTreeNode)curNode.getChildAt(i);
				FileNode fNode = (FileNode)childNode.getUserObject();
				String str =  fNode.getLocation();
				str = str.substring(str.lastIndexOf(File.separator) + 1);
				if(str.equals(c)) {
					curNode = childNode;
					getV_trmFileSystem().loadFileSystemPath(curNode);
					break;
				}
			}
		}
		
		TreePath toPath = new TreePath(curNode.getPath());
		getV_treeFileSystem().setSelectionPath(toPath);
		getV_treeFileSystem().expandPath(toPath);
	}

	private JLabel getV_lblStatus() {
		if (v_lblStatus == null) {
			v_lblStatus = new JLabel("我是状态栏");
		}
		return v_lblStatus;
	}

	private JList getV_listFiles() {
		if(v_listFiles == null) {
			v_listFiles = new JList(new DefaultListModel());
			v_listFiles.setLayoutOrientation(JList.VERTICAL_WRAP);
			v_listFiles.setVisibleRowCount(15);
			TabListCellRenderer renderer = new TabListCellRenderer();
			renderer.setTabs(new int[] {50, 200, 300});
			v_listFiles.setCellRenderer(renderer);
		}
		return v_listFiles;
	}

	private JMenuBar getV_mbar() {
		if (v_mbar == null) {
			v_mbar = new JMenuBar();
			v_mbar.add(getV_menuFile());
			v_mbar.add(getV_menuEdit());
			v_mbar.add(getV_menuView());
		}
		return v_mbar;
	}

	private JScrollPane getV_scr4Files() {
		if(v_scr4Files == null) {
			v_scr4Files = new JScrollPane();
			//v_scr4Files.setViewportView(getV_listFiles());
			v_scr4Files.setViewportView(getV_tblFiles());
		}
		return v_scr4Files;
	}

	private JSplitPane getV_splPane() {
		if (v_splPane == null) {
			v_splPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, false,
					getV_scr4Tree(), getV_scr4Files());
			v_splPane.setDividerSize(2);
			v_splPane.setDividerLocation(200);
		}
		return v_splPane;
	}

	private FileSystemTreeModel getV_trmFileSystem() {
		if(v_trmFileSystem == null) {
			v_trmFileSystem = new FileSystemTreeModel();
		}
		return v_trmFileSystem;
	}

	private JTree getV_treeFileSystem() {
		if (v_treeFileSystem == null) {
			v_treeFileSystem = new JTree(getV_trmFileSystem());
		}
		return v_treeFileSystem;
	}

	private JMenu getV_menuEdit() {
		if (v_menuEdit == null) {
			v_menuEdit = new JMenu("编辑");
			JMenuItem cut = new JMenuItem("剪切");
			JMenuItem copy = new JMenuItem("复制");
			JMenuItem paste = new JMenuItem("粘贴");
			v_menuEdit.add(cut);
			v_menuEdit.add(copy);
			v_menuEdit.add(paste);
		}
		return v_menuEdit;
	}

	private JMenu getV_menuFile() {
		if (v_menuFile == null) {
			v_menuFile = new JMenu("文件");
			JMenuItem newf = new JMenuItem("新建");
			JMenuItem open = new JMenuItem("打开");
			JMenuItem close = new JMenuItem("关闭");
			JMenuItem exit = new JMenuItem("退出");
			v_menuFile.add(newf);
			v_menuFile.add(open);
			v_menuFile.add(close);
			v_menuFile.add(exit);
		}
		return v_menuFile;
	}

	private JPanel getV_pnlStatus() {
		if (v_pnlStatus == null) {
			v_pnlStatus = new JPanel(new BorderLayout());
			v_pnlStatus.setBorder(new BevelBorder(BevelBorder.LOWERED));
			v_pnlStatus.add(getV_lblStatus(), BorderLayout.CENTER);
		}
		return v_pnlStatus;
	}

	private JPanel getV_mainPane() {
		if (v_mainPane == null) {
			v_mainPane = new JPanel(new BorderLayout());
			v_mainPane.add(getV_splPane());
		}
		return v_mainPane;
	}

	private JScrollPane getV_scr4Tree() {
		if (v_scr4Tree == null) {
			v_scr4Tree = new JScrollPane();
			v_scr4Tree.setViewportView(getV_treeFileSystem());
		}
		return v_scr4Tree;
	}

	private JTable getV_tblFiles() {
		if(v_tblFiles == null) {
			v_tblFiles = new JTable(getV_tbmFiles());
		}
		return v_tblFiles;
	}

	private DefaultTableModel getV_tbmFiles() {
		if(v_tbmFiles == null) {
			v_tbmFiles = new DefaultTableModel(null, new String[]{"文件名", "类型", "大小", "修改日期"});
		}
		return v_tbmFiles;
	}

	private JMenu getV_menuView() {
		if(v_menuView == null) {
			v_menuView = new JMenu("显示");
			ButtonGroup bg = new ButtonGroup();
			bg.add(getV_miDetail());
			bg.add(getV_miList());
			v_menuView.add(getV_miDetail());
			v_menuView.add(getV_miList());
			v_menuView.addSeparator();
			v_menuView.add(getV_miShowFileInTree());
			
			getV_miDetail().addActionListener(this);
			getV_miList().addActionListener(this);
			getV_miShowFileInTree().addActionListener(this);
			
		}
		return v_menuView;
	}

	private FileExplorerContext getV_context() {
		if(v_context == null) {
			v_context = new FileExplorerContext();
		}
		return v_context;
	}

	private JMenuItem getV_miShowFileInTree() {
		if(v_miShowFileInTree == null) {
			v_miShowFileInTree = new JCheckBoxMenuItem("在左边也显示文件");
		}
		return v_miShowFileInTree;
	}

	private JPanel getV_pnlURL() {
		if( v_pnlURL == null ) {
			v_pnlURL = new JPanel(new BorderLayout());
			v_pnlURL.add(new JLabel("地址:"), BorderLayout.WEST);
			v_pnlURL.add(getV_cmbURL(), BorderLayout.CENTER);
		}
		return v_pnlURL;
	}

	private JMenuItem getV_miDetail() {
		if(v_miDetail == null) {
			v_miDetail = new JRadioButtonMenuItem("详细");
			v_miDetail.setSelected(true); // 此时还未绑定Listener，不过要的就是这个效果
		}
		return v_miDetail;
	}

	private JMenuItem getV_miList() {
		if(v_miList == null) {
			v_miList = new JRadioButtonMenuItem("列表");
		}
		return v_miList;
	}

	private MemComboBox getV_cmbURL() {
		if(v_cmbURL == null ) {
			v_cmbURL = new MemComboBox();
		}
		return v_cmbURL;
	}
}